package com.ldf.media.callback;

import com.aizuda.zlm4j.callback.IMKStreamChangeCallBack;
import com.aizuda.zlm4j.structure.MK_MEDIA_SOURCE;
import com.ldf.media.api.service.ITranscodeService;
import com.ldf.media.config.MediaServerConfig;
import com.ldf.media.context.MediaServerContext;
import com.sun.jna.CallbackThreadInitializer;
import com.sun.jna.Native;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static com.ldf.media.constants.MediaServerConstants.*;

/**
 * 注册或反注册MediaSource事件广播
 *
 * @author lidaofu
 * @since 2023/11/23
 **/
@Component
@Slf4j
public class MKStreamChangeCallBack implements IMKStreamChangeCallBack {
    @Autowired
    private ITranscodeService transcodeService;
    @Autowired
    private MediaServerConfig config;

    public MKStreamChangeCallBack() {
        Native.setCallbackThreadInitializer(this, new CallbackThreadInitializer(true, false, "MediaStreamChangeThread"));
    }

    /**
     * 注册或反注册MediaSource事件广播
     *
     * @param regist 注册为1，注销为0
     * @param sender 该MediaSource对象
     */
    public void invoke(int regist, MK_MEDIA_SOURCE sender) {
        //这里进行流状态处理
        String stream = MediaServerContext.ZLM_API.mk_media_source_get_stream(sender);
        String app = MediaServerContext.ZLM_API.mk_media_source_get_app(sender);
        String schema = MediaServerContext.ZLM_API.mk_media_source_get_schema(sender);
        //如果是regist是注销情况下无法获取流详细信息如观看人数等
        log.info("【MediaServer】APP:{} 流:{} 协议：{} {}", app, stream, schema, regist == 1 ? "注册" : "注销");
        if (schema.equals("rtmp")&&regist==0){
            transcodeService.stopTranscode(stream);
        }

        //当流有新的观看者或流关闭时触发
//        String streamId = buildStreamId(sender);
//
//        // 根据配置决定是否立即关闭流
//        if (config.getAuto_close() == 0) {
//            // 立即关闭流
////            刚创建的流不会马上关闭；
////            前端有足够时间发起播放请求；
////            保证 WebRTC/RTMP/HLS 流稳定存在直到真正无人观看；
////            可以通过配置控制是否启用自动关闭功能。
////            MediaServerContext.ZLM_API.mk_media_source_close(sender, 0);
////            playerCountMap.remove(streamId);
////            log.info("流 {} 已关闭", streamId);
//        } else {
//            log.info("流 {} 暂时无人观看，保持连接", streamId);
//        }
//
//        if (regist == 0) { // type 0 表示流被关闭
//            // 从计数器中移除
//            playerCountMap.remove(streamId);
//
//            // 从活动流中移除
//            streamLastActiveTime.remove(streamId);
//
//            log.info("流 {} 已关闭", streamId);
//        } else { // type > 0 表示有新的观看者
//            // 更新最后活动时间
//            streamLastActiveTime.put(streamId, System.currentTimeMillis());
//
//            // 更新播放器计数
//            playerCountMap.put(streamId, playerCountMap.getOrDefault(streamId, 0) + 1);
//
//            log.info("流 {} 开始播放，当前播放器数量：{}", streamId, playerCountMap.get(streamId));
//        }
    }



    /**
     * 初始化定时任务
     */
    @PostConstruct
    public void init() {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        scheduler.scheduleAtFixedRate(() -> {
            try {
                // 清理无效流
                cleanupInvalidStreams();

                // 打印当前播放流数量
                log.info("当前正在播放的流数量：{}", getActiveStreamCount());
            } catch (Exception e) {
                log.error("流状态监控任务发生异常", e);
            }
        }, 0, 30, TimeUnit.SECONDS); // 每30秒检查一次
    }

    /**
     * 构建唯一的流标识符
     */
    private String buildStreamId(MK_MEDIA_SOURCE source) {
        return String.format("%s/%s",
                MediaServerContext.ZLM_API.mk_media_source_get_app(source),
                MediaServerContext.ZLM_API.mk_media_source_get_stream(source));
    }

    /**
     * 获取当前活跃的流数量
     */
    public static int getActiveStreamCount() {
        return (int) streamLastActiveTime.entrySet().stream()
                .filter(entry -> !isStreamTimeout(entry.getValue()))
                .count();
    }

    /**
     * 清理超时流
     */
    private void cleanupInvalidStreams() {
        streamLastActiveTime.forEach((streamId, lastActiveTime) -> {
            if (isStreamTimeout(lastActiveTime)) {
                log.info("cleanupInvalidStreams:流 {} 已超时", streamId);
                // 查找流
                MK_MEDIA_SOURCE source = MediaServerContext.ZLM_API.mk_media_source_find2(
                        "rtmp", "defaultVhost",
                        streamId.split("/")[0],
                        streamId.split("/")[1], 0);

                if (source != null) {
                    //查看流是否在播放：
                    if(getActiveStreamCount()>0){
                        log.info("流 {} 正在播放，不能关闭", streamId);
                        return;
                    }
                    // 关闭流
                    MediaServerContext.ZLM_API.mk_media_source_close(source, 0);

                    // 更新计数器
                    playerCountMap.remove(streamId);

                    log.info("流 {} 已超时并关闭", streamId);
                }
            }
        });
    }

    /**
     * 判断流是否超时
     */
    private static boolean isStreamTimeout(long lastActiveTime) {
        return System.currentTimeMillis() - lastActiveTime > 600000; // 10分钟超时
    }
}
